<template>
  <div class="log-list">
    <div class="page-header">
      <div class="header-content">
        <h1>系统日志</h1>
        <p class="subtitle">查看系统操作日志和审计记录</p>
      </div>
      <div class="header-actions">
        <el-button @click="handleExport" class="action-btn">
          <el-icon><Download /></el-icon>
          导出日志
        </el-button>
        <el-button @click="handleClear" class="action-btn">
          <el-icon><Delete /></el-icon>
          清空日志
        </el-button>
      </div>
    </div>

    <!-- 搜索区域 -->
    <el-card class="search-card" shadow="never">
      <div class="search-header">
        <el-icon><Search /></el-icon>
        <span>搜索筛选</span>
      </div>
      <el-form :model="searchForm" inline class="search-form">
        <el-form-item label="操作用户" class="form-item">
          <el-input 
            v-model="searchForm.username" 
            placeholder="请输入操作用户"
            clearable
            class="search-input"
          />
        </el-form-item>
        <el-form-item label="操作类型" class="form-item">
          <el-select v-model="searchForm.operationType" placeholder="请选择操作类型" clearable class="search-select">
            <el-option label="登录" value="LOGIN" />
            <el-option label="登出" value="LOGOUT" />
            <el-option label="新增" value="CREATE" />
            <el-option label="修改" value="UPDATE" />
            <el-option label="删除" value="DELETE" />
            <el-option label="查询" value="QUERY" />
            <el-option label="导出" value="EXPORT" />
            <el-option label="导入" value="IMPORT" />
          </el-select>
        </el-form-item>
        <el-form-item label="操作模块" class="form-item">
          <el-select v-model="searchForm.module" placeholder="请选择操作模块" clearable class="search-select">
            <el-option label="用户管理" value="USER" />
            <el-option label="角色管理" value="ROLE" />
            <el-option label="权限管理" value="PERMISSION" />
            <el-option label="商品管理" value="PRODUCT" />
            <el-option label="供应商管理" value="SUPPLIER" />
            <el-option label="溯源管理" value="TRACEABILITY" />
            <el-option label="质量管理" value="QUALITY" />
            <el-option label="系统管理" value="SYSTEM" />
          </el-select>
        </el-form-item>
        <el-form-item label="操作时间" class="form-item">
          <el-date-picker
            v-model="searchForm.timeRange"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            format="YYYY-MM-DD HH:mm:ss"
            value-format="YYYY-MM-DD HH:mm:ss"
            class="search-date-picker"
          />
        </el-form-item>
        <el-form-item label="IP地址" class="form-item">
          <el-input 
            v-model="searchForm.ipAddress" 
            placeholder="请输入IP地址"
            clearable
            class="search-input"
          />
        </el-form-item>
        <el-form-item class="form-item">
          <el-button type="primary" @click="handleSearch" class="search-btn">
            <el-icon><Search /></el-icon>
            搜索
          </el-button>
          <el-button @click="handleReset" class="reset-btn">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 日志表格 -->
    <el-card class="table-card" shadow="never">
      <div class="table-header">
        <div class="table-info">
          <span class="info-text">共 {{ filteredLogList.length }} 条日志</span>
          <span v-if="selectedLogs.length > 0" class="selected-info">
            已选择 {{ selectedLogs.length }} 项
          </span>
        </div>
        <div class="table-actions">
          <el-button size="small" :disabled="selectedLogs.length === 0" @click="handleBatchExport">
            批量导出
          </el-button>
        </div>
      </div>
      
      <div v-if="error" class="error-message">
        <el-icon><Warning /></el-icon>
        <span>{{ error }}</span>
      </div>
      
      <div v-if="loading" class="loading-container">
        <el-loading-spinner type="circle" size="large"></el-loading-spinner>
        <p>正在加载日志数据...</p>
      </div>
      
      <el-table 
        v-if="dataLoadSuccess" 
        :data="displayLogList" 
        class="log-table"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column type="index" label="序号" width="60" align="center">
          <template #default="scope">
            <span class="index-text">{{ (pagination.current - 1) * pagination.size + scope.$index + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="username" label="操作用户" width="120" />
        <el-table-column prop="operationType" label="操作类型" width="100" align="center">
          <template #default="scope">
            <el-tag :type="getOperationTypeTagType(scope.row.operationType)" size="small">
              {{ getOperationTypeText(scope.row.operationType) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="module" label="操作模块" width="120" align="center">
          <template #default="scope">
            <el-tag type="info" size="small">{{ getModuleText(scope.row.module) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="description" label="操作描述" min-width="200" show-overflow-tooltip />
        <el-table-column prop="ipAddress" label="IP地址" width="130" />
        <el-table-column prop="userAgent" label="用户代理" width="150" show-overflow-tooltip />
        <el-table-column prop="operationTime" label="操作时间" width="160" align="center">
          <template #default="scope">
            <span>{{ formatDateTime(scope.row.operationTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="120" align="center" fixed="right">
          <template #default="scope">
            <el-button size="small" type="primary" @click="handleViewDetail(scope.row)">查看详情</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pagination.current"
          v-model:page-size="pagination.size"
          :page-sizes="[10, 20, 50, 100]"
          :total="filteredLogList.length"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 日志详情对话框 -->
    <el-dialog
      v-model="detailDialogVisible"
      title="日志详情"
      width="800px"
      :close-on-click-modal="false"
    >
      <div v-if="currentLog" class="log-detail">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="日志ID">{{ currentLog.id }}</el-descriptions-item>
          <el-descriptions-item label="操作用户">{{ currentLog.username }}</el-descriptions-item>
          <el-descriptions-item label="操作类型">
            <el-tag :type="getOperationTypeTagType(currentLog.operationType)" size="small">
              {{ getOperationTypeText(currentLog.operationType) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="操作模块">
            <el-tag type="info" size="small">{{ getModuleText(currentLog.module) }}</el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="IP地址">{{ currentLog.ipAddress }}</el-descriptions-item>
          <el-descriptions-item label="操作时间">{{ formatDateTime(currentLog.operationTime) }}</el-descriptions-item>
          <el-descriptions-item label="操作描述" :span="2">{{ currentLog.description }}</el-descriptions-item>
          <el-descriptions-item label="请求URL" :span="2">{{ currentLog.requestUrl || '-' }}</el-descriptions-item>
          <el-descriptions-item label="请求方法">{{ currentLog.requestMethod || '-' }}</el-descriptions-item>
          <el-descriptions-item label="响应状态">{{ currentLog.responseStatus || '-' }}</el-descriptions-item>
          <el-descriptions-item label="用户代理" :span="2">{{ currentLog.userAgent || '-' }}</el-descriptions-item>
          <el-descriptions-item label="请求参数" :span="2">
            <div class="json-content">
              <pre>{{ formatJson(currentLog.requestParams) }}</pre>
            </div>
          </el-descriptions-item>
          <el-descriptions-item label="响应结果" :span="2">
            <div class="json-content">
              <pre>{{ formatJson(currentLog.responseResult) }}</pre>
            </div>
          </el-descriptions-item>
          <el-descriptions-item label="执行时长">{{ currentLog.executionTime ? `${currentLog.executionTime}ms` : '-' }}</el-descriptions-item>
          <el-descriptions-item label="错误信息">{{ currentLog.errorMessage || '-' }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <el-button @click="detailDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { defineComponent, ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { request } from '@/utils/request'
import { Search, Warning, Download, Delete } from '@element-plus/icons-vue'
import dayjs from 'dayjs'

export default defineComponent({
  name: 'LogList',
  components: {
    Search,
    Warning,
    Download,
    Delete
  },
  setup() {
    // 响应式数据
    const loading = ref(false)
    const error = ref('')
    const dataLoadSuccess = ref(false)
    const detailDialogVisible = ref(false)
    const selectedLogs = ref([])
    const currentLog = ref(null)

    // 日志列表数据
    const logList = ref([])

    // 搜索表单
    const searchForm = reactive({
      username: '',
      operationType: '',
      module: '',
      timeRange: [],
      ipAddress: ''
    })

    // 分页配置
    const pagination = reactive({
      current: 1,
      size: 20
    })

    // 计算属性
    const filteredLogList = computed(() => {
      let filtered = logList.value

      if (searchForm.username) {
        filtered = filtered.filter(log => 
          log.username.toLowerCase().includes(searchForm.username.toLowerCase())
        )
      }

      if (searchForm.operationType) {
        filtered = filtered.filter(log => log.operationType === searchForm.operationType)
      }

      if (searchForm.module) {
        filtered = filtered.filter(log => log.module === searchForm.module)
      }

      if (searchForm.timeRange && searchForm.timeRange.length === 2) {
        const [startTime, endTime] = searchForm.timeRange
        filtered = filtered.filter(log => {
          const logTime = dayjs(log.operationTime)
          return logTime.isAfter(startTime) && logTime.isBefore(endTime)
        })
      }

      if (searchForm.ipAddress) {
        filtered = filtered.filter(log => 
          log.ipAddress.includes(searchForm.ipAddress)
        )
      }

      return filtered
    })

    const displayLogList = computed(() => {
      const start = (pagination.current - 1) * pagination.size
      const end = start + pagination.size
      return filteredLogList.value.slice(start, end)
    })

    // 方法
    const loadLogList = async () => {
      loading.value = true
      error.value = ''
      
      try {
        const response = await request.get('/logs')
        logList.value = response.data || []
        dataLoadSuccess.value = true
      } catch (err) {
        error.value = '加载日志数据失败'
        console.error('Load log list error:', err)
      } finally {
        loading.value = false
      }
    }

    const handleSearch = () => {
      pagination.current = 1
    }

    const handleReset = () => {
      Object.keys(searchForm).forEach(key => {
        if (key === 'timeRange') {
          searchForm[key] = []
        } else {
          searchForm[key] = ''
        }
      })
      pagination.current = 1
    }

    const handleViewDetail = (row) => {
      currentLog.value = row
      detailDialogVisible.value = true
    }

    const handleExport = async () => {
      try {
        const params = {
          ...searchForm,
          startTime: searchForm.timeRange?.[0],
          endTime: searchForm.timeRange?.[1]
        }
        
        await request.get('/logs/export', { 
          params,
          responseType: 'blob'
        })
        
        ElMessage.success('日志导出成功')
      } catch (err) {
        ElMessage.error('日志导出失败')
      }
    }

    const handleClear = async () => {
      try {
        await ElMessageBox.confirm(
          '确定要清空所有日志吗？此操作不可恢复！',
          '确认清空',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }
        )

        await request.delete('/logs/clear')
        ElMessage.success('日志清空成功')
        loadLogList()
      } catch (err) {
        if (err !== 'cancel') {
          ElMessage.error('日志清空失败')
        }
      }
    }

    const handleBatchExport = async () => {
      if (selectedLogs.value.length === 0) return

      try {
        const ids = selectedLogs.value.map(log => log.id)
        await request.post('/logs/batch-export', { ids }, { responseType: 'blob' })
        ElMessage.success('批量导出成功')
      } catch (err) {
        ElMessage.error('批量导出失败')
      }
    }

    const handleSelectionChange = (selection) => {
      selectedLogs.value = selection
    }

    const handleSizeChange = (size) => {
      pagination.size = size
      pagination.current = 1
    }

    const handleCurrentChange = (current) => {
      pagination.current = current
    }

    const getOperationTypeTagType = (type) => {
      const typeMap = {
        'LOGIN': 'success',
        'LOGOUT': 'info',
        'CREATE': 'primary',
        'UPDATE': 'warning',
        'DELETE': 'danger',
        'QUERY': 'info',
        'EXPORT': 'success',
        'IMPORT': 'warning'
      }
      return typeMap[type] || 'info'
    }

    const getOperationTypeText = (type) => {
      const typeMap = {
        'LOGIN': '登录',
        'LOGOUT': '登出',
        'CREATE': '新增',
        'UPDATE': '修改',
        'DELETE': '删除',
        'QUERY': '查询',
        'EXPORT': '导出',
        'IMPORT': '导入'
      }
      return typeMap[type] || type
    }

    const getModuleText = (module) => {
      const moduleMap = {
        'USER': '用户管理',
        'ROLE': '角色管理',
        'PERMISSION': '权限管理',
        'PRODUCT': '商品管理',
        'SUPPLIER': '供应商管理',
        'TRACEABILITY': '溯源管理',
        'QUALITY': '质量管理',
        'SYSTEM': '系统管理'
      }
      return moduleMap[module] || module
    }

    const formatDateTime = (dateTime) => {
      if (!dateTime) return '-'
      return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss')
    }

    const formatJson = (jsonString) => {
      if (!jsonString) return '-'
      try {
        const parsed = JSON.parse(jsonString)
        return JSON.stringify(parsed, null, 2)
      } catch {
        return jsonString
      }
    }

    // 生命周期
    onMounted(() => {
      loadLogList()
    })

    return {
      loading,
      error,
      dataLoadSuccess,
      detailDialogVisible,
      selectedLogs,
      currentLog,
      logList,
      searchForm,
      pagination,
      filteredLogList,
      displayLogList,
      handleSearch,
      handleReset,
      handleViewDetail,
      handleExport,
      handleClear,
      handleBatchExport,
      handleSelectionChange,
      handleSizeChange,
      handleCurrentChange,
      getOperationTypeTagType,
      getOperationTypeText,
      getModuleText,
      formatDateTime,
      formatJson
    }
  }
})
</script>

<style lang="scss" scoped>
@use '../../styles/variables.scss' as *;
@use '../../styles/responsive.scss' as *;
@use '../../styles/common.scss' as *;

.log-list {
  padding: 20px;
  
  @include respond-to(xs) {
    padding: 12px;
  }
}

.page-header {
  @include flex-between;
  margin-bottom: 20px;
  
  @include respond-to(xs) {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }
  
  .header-content {
    h1 {
      margin: 0 0 4px 0;
      font-size: 24px;
      font-weight: 600;
      color: var(--text-color-primary);
    }
    
    .subtitle {
      margin: 0;
      color: var(--text-color-secondary);
      font-size: 14px;
    }
  }
  
  .header-actions {
    @include flex-center;
    gap: 8px;
    
    .action-btn {
      @include flex-center;
      gap: 4px;
    }
  }
}

.search-card {
  margin-bottom: 20px;
  
  .search-header {
    @include flex-center;
    gap: 8px;
    margin-bottom: 16px;
    font-weight: 500;
    color: var(--text-color-primary);
  }
  
  .search-form {
    .form-item {
      margin-bottom: 12px;
      
      .search-input,
      .search-select {
        width: 200px;
        
        @include respond-to(xs) {
          width: 100%;
        }
      }
      
      .search-date-picker {
        width: 300px;
        
        @include respond-to(xs) {
          width: 100%;
        }
      }
    }
    
    .search-btn,
    .reset-btn {
      @include flex-center;
      gap: 4px;
    }
  }
}

.table-card {
  .table-header {
    @include flex-between;
    margin-bottom: 16px;
    
    .table-info {
      @include flex-center;
      gap: 12px;
      
      .info-text {
        color: var(--text-color-secondary);
        font-size: 14px;
      }
      
      .selected-info {
        color: var(--primary-color);
        font-size: 14px;
        font-weight: 500;
      }
    }
  }
  
  .error-message {
    @include flex-center;
    gap: 8px;
    padding: 20px;
    color: var(--danger-color);
    background: var(--danger-bg);
    border-radius: 4px;
    margin-bottom: 16px;
  }
  
  .loading-container {
    @include flex-center;
    flex-direction: column;
    gap: 12px;
    padding: 40px;
    color: var(--text-color-secondary);
  }
}

.log-table {
  .index-text {
    color: var(--text-color-secondary);
    font-size: 13px;
  }
}

.pagination-container {
  @include flex-center;
  margin-top: 20px;
}

.log-detail {
  .json-content {
    background: var(--bg-color-secondary);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 12px;
    max-height: 200px;
    overflow-y: auto;
    
    pre {
      margin: 0;
      font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
      font-size: 12px;
      line-height: 1.4;
      color: var(--text-color-primary);
      white-space: pre-wrap;
      word-break: break-all;
    }
  }
}
</style> 